package com.hopes.bizz.risk.job;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.common.core.annotation.TenantJobRun;
import com.hopes.bizz.risk.common.constant.HidDicConstant;
import com.hopes.bizz.risk.hid.bo.HidPlanCycleDateBO;
import com.hopes.bizz.risk.hid.bo.HidTaskNumberProducerBO;
import com.hopes.bizz.risk.hid.entity.RiskHidCheckContentConfigEntity;
import com.hopes.bizz.risk.hid.entity.RiskHidCheckPlanEntity;
import com.hopes.bizz.risk.hid.entity.RiskHidCheckTaskEntity;
import com.hopes.bizz.risk.hid.entity.RiskHidCheckTaskRecordEntity;
import com.hopes.bizz.risk.hid.service.RiskHidCheckContentConfigService;
import com.hopes.bizz.risk.hid.service.RiskHidCheckPlanService;
import com.hopes.bizz.risk.hid.service.RiskHidCheckTaskRecordService;
import com.hopes.bizz.risk.hid.service.RiskHidCheckTaskService;
import com.hopes.bizz.risk.hid.vo.RiskHidCheckTaskVO;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 检查计划任务生成
 * @time 2023/8/17 15:01
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RiskHiddenPlanGenerateService {


    private final RiskHidCheckPlanService riskHidCheckPlanService;
    private final RiskHidCheckTaskService riskHidCheckTaskService;
    private final RiskHidCheckTaskRecordService riskHidCheckTaskRecordService;
    private final RiskHidCheckContentConfigService riskHidCheckContentConfigService;


    @TenantJobRun
    @Transactional(rollbackFor = Exception.class)
    @XxlJob("riskHiddenPlanGenerateJobHandler")
    public void riskHiddenPlanGenerateJobHandler() {
        final Date date = Calendar.getInstance().getTime();

        // 1、查询正在运行的检查计划
        final List<RiskHidCheckPlanEntity> riskHidCheckPlanEntityList = listIsRunningCheckPlan(date);

        // 2、创建任务
        final List<RiskHidCheckTaskVO> riskHidCheckTaskList = createHidCheckTaskList(date, riskHidCheckPlanEntityList);
        for (RiskHidCheckTaskVO riskHidCheckTaskVO : riskHidCheckTaskList) {
            final RiskHidCheckTaskEntity checkTaskEntity = new RiskHidCheckTaskEntity();
            BeanUtils.copyProperties(riskHidCheckTaskVO, checkTaskEntity);
            riskHidCheckTaskService.save(checkTaskEntity);

            final List<RiskHidCheckTaskRecordEntity> collect = riskHidCheckTaskVO.getContentConfigs().stream().map(item -> {
                final RiskHidCheckTaskRecordEntity record = new RiskHidCheckTaskRecordEntity();
                record.setWay(item.getWay());
                record.setItem(item.getItem());
                record.setBasis(item.getBasis());
                record.setContent(item.getContent());
                record.setTaskId(checkTaskEntity.getId());
                record.setRiskHidCheckContentConfigId(item.getId());
                record.setRiskHidCheckListConfigId(item.getRiskHidCheckListConfigId());
                record.setConclusion(HidDicConstant.RISK_HID_CHECKLIST_TASK_CONCLUSION_NOT_CHECKED);
                return record;
            }).collect(Collectors.toList());
            riskHidCheckTaskRecordService.saveBatch(collect);
        }

        // 3、更新计划
        final List<RiskHidCheckPlanEntity> collect = riskHidCheckPlanEntityList.parallelStream().map(item -> {
            final RiskHidCheckPlanEntity riskHidCheckPlanEntity = new RiskHidCheckPlanEntity();
            final HidPlanCycleDateBO hidPlanCycleDate = new HidPlanCycleDateBO(item.getPushCycle(), item.getPushDate(), item.getPushTime());
            riskHidCheckPlanEntity.setId(item.getId());
            riskHidCheckPlanEntity.setNextExecuteDate(hidPlanCycleDate.getPlanDate());
            return riskHidCheckPlanEntity;
        }).collect(Collectors.toList());
        riskHidCheckPlanService.updateBatchById(collect);
    }

    /**
     * 查询正在运行的检查计划
     * @return 正在运行的检查计划
     */
    private List<RiskHidCheckPlanEntity> listIsRunningCheckPlan(Date date) {
        final LambdaQueryWrapper<RiskHidCheckPlanEntity> queryWrapper = Wrappers.<RiskHidCheckPlanEntity>lambdaQuery()
                .eq(RiskHidCheckPlanEntity::getRunFlag, Boolean.TRUE)
                .isNotNull(RiskHidCheckPlanEntity::getNextExecuteDate)
                .le(RiskHidCheckPlanEntity::getNextExecuteDate, date);
        return riskHidCheckPlanService.list(queryWrapper);
    }

    /**
     * 创建检查任务
     * @param date   事件
     * @param riskHidCheckPlanEntityList  检查计划
     * @return
     */
    private List<RiskHidCheckTaskVO> createHidCheckTaskList(Date date, List<RiskHidCheckPlanEntity> riskHidCheckPlanEntityList) {
        final List<RiskHidCheckTaskVO> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(riskHidCheckPlanEntityList)) {
            return result;
        }

        for (RiskHidCheckPlanEntity checkPlan : riskHidCheckPlanEntityList) {
            final RiskHidCheckTaskVO checkTask = new RiskHidCheckTaskVO();

            checkTask.setStartTime(date);
            checkTask.setPlanId(checkPlan.getId());
            checkTask.setRecorder(checkPlan.getRecorder());
            checkTask.setRiskUnitId(checkPlan.getRiskUnitId());
            checkTask.setCheckPerson(checkPlan.getCheckPerson());
            checkTask.setCheckObject(checkPlan.getCheckObject());
            checkTask.setRecorderIdCard(checkPlan.getRecorderIdCard());
            checkTask.setHidCheckListConfigId(checkPlan.getHidCheckListConfigId());

            final RiskHidCheckTaskEntity checkTaskEntity = riskHidCheckTaskService.getOne(
                    Wrappers.<RiskHidCheckTaskEntity>lambdaQuery()
                            .select(RiskHidCheckTaskEntity::getTaskNo)
                            .orderByDesc(RiskHidCheckTaskEntity::getTaskNo).last("limit 1"));

            final HidTaskNumberProducerBO producer = new HidTaskNumberProducerBO(Optional.ofNullable(checkTaskEntity).map(RiskHidCheckTaskEntity::getTaskNo).orElse(null));
            checkTask.setTaskNo(producer.getTaskNo());
            checkTask.setTaskStatus(HidDicConstant.RISK_HID_CHECKLIST_TASK_STATUS_TODO);
            checkTask.setTaskConclusion(HidDicConstant.RISK_HID_CHECKLIST_TASK_CONCLUSION_NOT_CHECKED);
            checkTask.setDeadline(DateUtil.offsetHour(checkPlan.getNextExecuteDate(), checkPlan.getMaxHandleHour()));
            checkTask.setTaskName(checkPlan.getPlanName() + "(" + DateUtil.format(new Date(), "yyyyMMddHHmm") + ")");

            final String hidCheckListConfigId = checkPlan.getHidCheckListConfigId();
            if (StrUtil.isNotEmpty(hidCheckListConfigId)) {
                final List<RiskHidCheckContentConfigEntity> list = riskHidCheckContentConfigService.list(Wrappers.<RiskHidCheckContentConfigEntity>lambdaQuery().in(RiskHidCheckContentConfigEntity::getRiskHidCheckListConfigId, hidCheckListConfigId));
                checkTask.setTotalNum(list.size());
                checkTask.setContentConfigs(list);
            }
            result.add(checkTask);
        }
        return result;
    }

}
